// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v13;

import com.google.api.adwords.lib.AdWordsService;
import com.google.api.adwords.lib.AdWordsServiceLogger;
import com.google.api.adwords.lib.AdWordsUser;
import com.google.api.adwords.v13.AccountInfo;
import com.google.api.adwords.v13.AccountInterface;
import com.google.api.adwords.v13.ApiException;
import com.google.api.adwords.v13.ClientAccountInfo;

import java.rmi.RemoteException;

import javax.xml.rpc.ServiceException;

/**
 * This demo displays all accounts below the effective user of the root
 * {@code AdWordsUser} account.
 */
public class GetAccountTreeDemo {
  public static void main(String[] args) throws Exception {
    // Log SOAP XML request and response.
    AdWordsServiceLogger.log();

    // Get AdWordsUser from "~/adwords.properties".
    AdWordsUser user = new AdWordsUser();

    // Get AccountService.
    AccountInterface accountService = user.getService(AdWordsService.V13.ACCOUNT_SERVICE);

    // You can clear the clientId retrieved from "~/adwords.properties" by
    // uncommenting the line below.
    // user = user.generateClientAdWordsUser(null);

    displayTree(user);
  }

  /**
   * Displays the account tree beginning at the root user.
   *
   * @param root the root user
   */
  private static void displayTree(AdWordsUser root)
      throws ServiceException, RemoteException, ApiException{
    displayTreeHelper(root, 0);
  }

  /**
   * Helper for displaying the account tree.
   *
   * @param root the root user
   * @param depth the depth the tree has reached
   */
  private static void displayTreeHelper(AdWordsUser root, int depth)
      throws ServiceException, RemoteException, ApiException {
    // Get AccountService.
    AccountInterface accountService = root.getService(AdWordsService.V13.ACCOUNT_SERVICE);

    // Get the account info.
    AccountInfo accountInfo = accountService.getAccountInfo();

    // Output the client and its customer Id.
    System.out.println(generateTab(depth) + root.getEffectiveUserId()
        + " : " + formatCid(accountInfo.getCustomerId()));

    // Get all clients below this user.
    ClientAccountInfo[] clientAccountInfos = accountService.getClientAccountInfos();

    if (clientAccountInfos != null) {
      for (ClientAccountInfo clientAccountInfo : clientAccountInfos) {
        displayTreeHelper(
            root.generateClientAdWordsUser(clientAccountInfo.getEmailAddress()), depth + 1);
      }
    }
  }

  /**
   * Generates a {@code String} of tabs to represent branching to children.
   *
   * @param depth a depth from 0 to max(depth)
   * @return a {@code String} to insert in front of the root unit
   */
  private static String generateTab(int depth) {
    StringBuilder builder = new StringBuilder();
    if (depth != 0) {
      builder.append("  ");
    }

    for (int i = 1; i < depth; i++) {
      builder.append("|  ");
    }

    return builder.append("+--").toString();
  }

  /**
   * Formats the external CID into a human readable string; i.e. ###-###-####.
   *
   * @param externalCid the external CID to parse
   * @return the formated CID string
   */
  private static String formatCid(long externalCid) {
    String cidString = new Long(externalCid).toString();
    if (cidString.length() == 10) {
      StringBuffer cid = new StringBuffer()
          .append(cidString.substring(0, 3))
          .append("-")
          .append(cidString.substring(3, 7))
          .append("-")
          .append(cidString.substring(7, 10));
      return cid.toString();
    } else {
      return cidString;
    }
  }
}
